﻿#if NETSTANDARD2_0 || NETCOREAPP3_0
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
#else
using Longbow.Logging;
#endif
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Longbow.Tasks
{
    /// <summary>
    /// 后台服务工厂操作类
    /// </summary>
    internal sealed class TaskServicesFactory : IDisposable
#if NETSTANDARD2_0 || NETCOREAPP3_0
        , IHostedService
#endif
    {
        private CancellationTokenSource _shutdownCts = new CancellationTokenSource();
        private TaskServicesOptions _options;

#if NETSTANDARD2_0 || NETCOREAPP3_0
        internal static TaskServicesFactory Instance = null;
        /// <summary>
        /// 默认构造函数
        /// </summary>
        /// <param name="logger">ILogger(TaskServicesFactory) 实例</param>
        /// <param name="options">后台服务配置类实例</param>
        /// <param name="storage">IStorage 任务持久化接口实例</param>
        public TaskServicesFactory(ILogger<TaskServicesFactory> logger, IOptionsMonitor<TaskServicesOptions> options, IStorage storage)
        {
            Logger = logger;
            _options = options.CurrentValue;
            options.OnChange(op => _options = op);
            Storage = storage;
            Instance = this;
        }
#else
        /// <summary>
        /// 默认构造函数 
        /// </summary>
        /// <param name="logger">ILogger(TaskServicesFactory) 实例</param>
        /// <param name="options">后台服务配置类实例</param>
        /// <param name="storage">IStorage 任务持久化接口实例</param>
        public TaskServicesFactory(ILogger logger = null, TaskServicesOptions options = null, IStorage storage = null)
        {
            Logger = logger ?? new FileLoggerProvider(new FileLoggerOptions()).CreateLogger(nameof(TaskServicesFactory));
            Storage = storage;
            _options = options ?? new TaskServicesOptions();
        }
#endif

        /// <summary>
        /// 获得 日志实例
        /// </summary>
        public ILogger Logger { get; }

        /// <summary>
        /// 获得 任务持久化配置项实例
        /// </summary>
        public IStorage Storage { get; }

        /// <summary>
        /// IHostedService 接口异步开始方法
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task StartAsync(CancellationToken cancellationToken = default)
        {
            Log($"{nameof(TaskServicesFactory)} StartAsync() Started");
#if NETSTANDARD2_0 || NETCOREAPP3_0
            return Task.CompletedTask;
#else
            return Task.FromResult(0);
#endif
        }

        /// <summary>
        /// IHostedService 接口异步结束方法
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task StopAsync(CancellationToken cancellationToken)
        {
            Log($"{nameof(TaskServicesFactory)} -> {nameof(StopAsync)}() Shutdown After({_options.ShutdownTimeout})");
            _shutdownCts.CancelAfter(_options.ShutdownTimeout);
            WaitForShutdown(CancellationTokenSource.CreateLinkedTokenSource(_shutdownCts.Token, cancellationToken).Token);
#if NETSTANDARD2_0 || NETCOREAPP3_0
            return Task.CompletedTask;
#else
            return Task.FromResult(0);
#endif
        }

        private void WaitForShutdown(CancellationToken token)
        {
            TaskServicesManager.Shutdown(token);
            Log($"{nameof(TaskServicesFactory)} WaitForShutdown()");
        }

        /// <summary>
        /// 日志记录方法
        /// </summary>
        /// <param name="message">日志内容</param>
        public void Log(string message)
        {
            Logger.Log(LogLevel.Information, $"{DateTimeOffset.Now}: {message}");
        }

        /// <summary>
        /// Dispose 方法
        /// </summary>
        public void Dispose()
        {
            Log($"{nameof(TaskServicesFactory)} Disposed");
            if (_shutdownCts != null)
            {
                _shutdownCts.Dispose();
                _shutdownCts = null;
            }
        }
    }
}
